/**      
 * @file		unaryOperators.cpp
 * @description		This sample demonstrates operator overloading.
 *			This sample adds the >>, <<, ++ (pre and postfix) operators 
 *			to the Circle class.
 * @course		CSCI 123 Section 00000
 * @assignment 
 * @date		mm/dd/yyyy
 * @author		Brad Rippe (00000000) brippe@fullcoll.edu
 * @version		1.0
 */
#include <iostream>
using namespace std;

/**
 * Represents a circle
 */
class Circle {
public:
	/**
	 * Adds the radius of two circles and creates a new circle with the
	 * result of the addition.
	 * @param aCircle1 the left hand side circle
	 * @param aCircle2 the right hand side circle
	 * @return a new Circle with circle1's radius added to circle2's
	 */
	friend Circle operator +(const Circle& aCircle, const Circle& aCircle2);

	/**
	 * Subtracts the radius of two circles and creates a new circle with the
	 * result of the subtraction.
	 * @param aCircle1 the left hand side circle
	 * @param aCircle2 the right hand side circle
	 * @return a new Circle with circle2's radius subtracted from circle1's
	 */
	friend Circle operator -(const Circle& aCircle, const Circle& aCircle2);

	/**
	 * Adds the radius of two circles and creates a new circle with the
	 * result of the addition.
	 * @param aCircle1 the left hand side circle
	 * @param aCircle2 the right hand side circle
	 * @return a new Circle with radius of circle1's radius added to circle2's
	 */
	friend bool operator ==(const Circle& aCircle, const Circle& aCircle2);

	/**
	 * Increments the circles radius by one
	 * This is the prefix operator
	 * @param aCircle the circle to increment
	 * @return the circle after the radius is incremented
	 *			hence the prefix operator
	 */
	friend Circle operator ++(Circle& aCircle);

	/**
	 * Increments the circles radius by one
	 * This is the postfix operator
	 * @param aCircle the circle to increment
	 * @return the circle before the radius is incremented
	 *			hence the postfix operator
	 */
	friend Circle operator ++(Circle& aCircle, int aIncrement);

	/**
	 * Outputs a Circle
	 * @param aCircle the circle to output
	 * @return the output stream
	 */
	friend ostream& operator <<(ostream& aOutput, const Circle& aCircle);

	/**
	 * Input a Circle
	 * @param aCircle the circle to output
	 * @return the input stream
	 */
	friend istream& operator >>(istream& aInput, Circle& aCircle);

	/**
	 * Default constructor sets the circle's radius to 1
	 * @return a new Circle with the radius 1
	 */
	Circle();

	/**
	 * Constructor sets the circles radius.
	 * @param aRadius set the new circle's radius to aRadius
	 *			if aRadius is <= 0, returns a circle with a 
	 *			radius of 1
	 * @return a new circle with a radius of aRadius
	 */
	Circle(double aRadius);

	/**
	 * Returns the radius of the circle
	 * @return the radius of the circle
	 */
	double getRadius() const;

	/**
	 * Sets the radius of the circle
	 * @param aRadius the new radius of the circle
	 *			if aRadius is <= 0, the circle's radius
	 *			is set to 1
	 */
	void setRadius(double aRadius);

private:
	double mRadius;
};

/**
 * @return zero if the application executes successfully
 */
int main() {
	cout << "Circle circle1(24.0);\n";
	Circle circle1(24.0);
	cout << "Circle1's radius is (postfix ++) " << circle1++ << endl;
	cout << "Circle1's radius is " << circle1.getRadius() << endl;
	cout << endl;

	cout << "Circle1's radius is (prefix ++) " << ++circle1 << endl;
	cout << "Circle1's radius is " << circle1.getRadius() << endl;
	cout << endl;

	//Here's a sample use of the extraction operator for our circle class
	cout << "Please type a radius > 0\n";
	cin >> circle1;
	cout << "Circle1's radius is " << circle1 << endl;
	return 0;
}

/*
 * Friends of Circle
 */
Circle operator +(const Circle& aCircle, const Circle& aCircle2) {
	return Circle(aCircle.mRadius+aCircle2.mRadius);
}

Circle operator -(const Circle& aCircle, const Circle& aCircle2) {
	return Circle(aCircle.mRadius-aCircle2.mRadius);
}

bool operator ==(const Circle& aCircle, const Circle& aCircle2) {
	return (aCircle.mRadius == aCircle2.mRadius);
}

// prefix operator
// the pre and postfix operators are denoted by the
// int argument in the postfix declaration
Circle operator ++(Circle& aCircle) {
	// note we return a circle with the
	// radius value incremented
	return Circle(++aCircle.mRadius);
}

// postfix operator circle++
Circle operator ++(Circle& aCircle, int increment) {
	// note we return a circle with the original
	// radius value
	return Circle(aCircle.mRadius++);
}

// we can overload the << output operator
ostream& operator<<(ostream& aOutput, const Circle& aCircle) {
	aOutput << aCircle.mRadius;
	return aOutput;
}

// we can overload the >> output operator
// what does this mean for your object?
istream& operator>>(istream& aInput, Circle& aCircle) {
	aInput >> aCircle.mRadius;
	if(aCircle.mRadius < 1)
		aCircle.mRadius = 1;
	return aInput;
}

/*
* Members of a circle
*/
Circle::Circle() {
	mRadius = 1;
}

Circle::Circle(double aRadius) : mRadius(aRadius) {
	if(aRadius <= 0)
		mRadius = 1;
}

double Circle::getRadius() const {
	return mRadius;
}

void Circle::setRadius(double aRadius) {
	mRadius = aRadius;
}

